"""
2266. 统计打字方案数
中等
相关标签
相关企业
提示
Alice 在给 Bob 用手机打字。数字到字母的 对应 如下图所示。



为了 打出 一个字母，Alice 需要 按 对应字母 i 次，i 是该字母在这个按键上所处的位置。

比方说，为了按出字母 's' ，Alice 需要按 '7' 四次。类似的， Alice 需要按 '5' 两次得到字母  'k' 。
注意，数字 '0' 和 '1' 不映射到任何字母，所以 Alice 不 使用它们。
但是，由于传输的错误，Bob 没有收到 Alice 打字的字母信息，反而收到了 按键的字符串信息 。

比方说，Alice 发出的信息为 "bob" ，Bob 将收到字符串 "2266622" 。
给你一个字符串 pressedKeys ，表示 Bob 收到的字符串，请你返回 Alice 总共可能发出多少种文字信息 。

由于答案可能很大，将它对 109 + 7 取余 后返回。



示例 1：

输入：pressedKeys = "22233"
输出：8
解释：
Alice 可能发出的文字信息包括：
"aaadd", "abdd", "badd", "cdd", "aaae", "abe", "bae" 和 "ce" 。
由于总共有 8 种可能的信息，所以我们返回 8 。
示例 2：

输入：pressedKeys = "222222222222222222222222222222222222"
输出：82876089
解释：
总共有 2082876103 种 Alice 可能发出的文字信息。
由于我们需要将答案对 109 + 7 取余，所以我们返回 2082876103 % (109 + 7) = 82876089 。


提示：

1 <= pressedKeys.length <= 105
pressedKeys 只包含数字 '2' 到 '9' 。
"""
class P2266(object):
    def countTexts(self, pressedKeys):
        """
        :type pressedKeys: str
        :rtype: int
        整体思路：主要分两种情况讨论：
        1.如果和前面不同的字符，那么就直接和前面的数量一致，因为无法变化
        2.如果和前面字符相同，统计前面重复的次数times
        首先当前字符可以不和前面拼接，其实就是 dp[i-1]
        则看前面有多少个重复的
        如果times>=1则可以和前面的重复拼接成一个字母，然后他的情况就是不包括当前和前一个的所有情况，也就是dp[i-2] (不包括dp[i]和dp[i-1])
        同理如果>=2则....dp[i-3]
        特殊的，对于有四个的7和9，则可以 dp[i-4]

        """
        pLen = len(pressedKeys)
        if pLen < 2:
            return pLen
        pre = ''
        time = 0
        mod = 1e9 + 7
        dp = [0] * (pLen+1)
        dp[0] = 1
        for i in range(1,pLen + 1):
            dp[i] = dp[i-1]
            # 注意，当前的i是相对于pressedKeys索引+1，所以需要-1
            if pre == pressedKeys[i-1]:
                if time >= 1 and i-2>=0:
                    dp[i] = dp[i] + dp[i-2]
                if time >= 2 and i-3>=0:
                    dp[i] = dp[i] + dp[i-3]
                if (int(pressedKeys[i-1]) == 9 or int(pressedKeys[i-1]) == 7) and time >= 3 and i-4>=0:
                    dp[i] = dp[i] + dp[i-4]
                time += 1
            else:
                pre = pressedKeys[i - 1]
                time = 1
            dp[i] = dp[i] % mod
        return int(dp[pLen]%mod)

    def countTexts_2(self, pressedKeys):
        """
        :type pressedKeys: str
        :rtype: int
        整体思路：主要分两种情况讨论：
        1.
        """
        pLen = len(pressedKeys)
        if pLen < 2:
            return pLen
        pre = ''
        time = 0
        mod = 1e9 + 7
        dp = [0] * (pLen+1)
        dp[0] = 1
        for i in range(1,pLen + 1):
            dp[i] = dp[i-1]
            if str(pre) == str(pressedKeys[i-1]):
                if time >= 1 and i-2>=0:
                    dp[i] = int((dp[i] + dp[i-2])%mod)
                if time >= 2 and i-3>=0:
                    dp[i] = int((dp[i] + dp[i-3])%mod)
                if (pressedKeys[i-1] == '9' or pressedKeys[i-1] == '7') and time >= 3 and i-4>=0:
                    dp[i] = int((dp[i] + dp[i-4])%mod)
                time += 1
            else:
                pre = pressedKeys[i - 1]
                time = 1
        return int(dp[pLen]%mod)

# print(P2266().countTexts("22233"))
# print(P2266().countTexts("222222222222222222222222222222222222"))
print(P2266().countTexts("444479999555588866")) #3136
print(P2266().countTexts("444444444444444444444444444444448888888888888888999999999999333333333333333366666666666666662222222222222222666666666666666633333333333333338888888888888888222222222222222244444444444444448888888888888222222222222222288888888888889999999999999999333333333444444664")) #3136
print(P2266().countTexts_2("444444444444444444444444444444448888888888888888999999999999333333333333333366666666666666662222222222222222666666666666666633333333333333338888888888888888222222222222222244444444444444448888888888888222222222222222288888888888889999999999999999333333333444444664")) #3136
print(1=='1')